package com.dev.weixin.tools.service.impl;

import java.io.File;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.dev.weixin.tools.models.WeixinConfig;
import com.dev.weixin.tools.models.base.ErrorMsg;
import com.dev.weixin.tools.models.exceptions.ErrorMsgException;
import com.dev.weixin.tools.models.material.GraphicsTextMaterial;
import com.dev.weixin.tools.models.material.GraphicsTextMaterials;
import com.dev.weixin.tools.models.material.Material;
import com.dev.weixin.tools.models.material.MaterialCount;
import com.dev.weixin.tools.models.material.MaterialList;
import com.dev.weixin.tools.models.material.VideoMaterial;
import com.dev.weixin.tools.models.material.VideoMaterialGet;
import com.dev.weixin.tools.service.BaseService;
import com.dev.weixin.tools.service.MaterialService;
import com.dev.weixin.tools.utils.URLConstants;
import com.dev.weixin.tools.utils.WeixinHttpClient;
import com.dev.weixin.tools.utils.policy.DownloadRequestPolicy;
import com.dev.weixin.tools.utils.policy.ForceDownloadRequestPolicy;
import com.dev.weixin.tools.utils.policy.GetRequestPolicy;
import com.dev.weixin.tools.utils.policy.JsonRequestPolicy;
import com.dev.weixin.tools.utils.policy.RequestPolicy;
import com.dev.weixin.tools.utils.policy.UploadRequestPolicy;

/**
 * @author 飘渺青衣
 * @see
 */
@Service("weixinMaterialService")
public class MaterialServiceImpl implements MaterialService {

	private BaseService baseService;
	
	@Autowired
	public MaterialServiceImpl(BaseService baseService) {
		this.baseService = baseService;
	}
	
	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#addTempMaterial(java.lang.String, java.io.File)
	 */
	@Override
	public Material addTempMaterial(String type, File file) throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		params.put("type", type);
		Map<String, Object> body = new LinkedHashMap<String, Object>();
		body.put("media", file);
		RequestPolicy<Material> policy = new UploadRequestPolicy<Material>(
				URLConstants.Material.URL_MATERIAL_ADDTEMPMATERIAL,
				WeixinConfig.ENCODING,
				params, body, Material.class);
		return WeixinHttpClient.request(policy);
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#getTempMaterial(java.lang.String, java.lang.String)
	 */
	@Override
	public File getTempMaterial(String media_id, String filedir)
			throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		params.put("media_id", media_id);
		RequestPolicy<File> policy = new DownloadRequestPolicy(
				URLConstants.Material.URL_MATERIAL_GETTEMPMATERIAL,
				WeixinConfig.ENCODING,
				params, null, filedir);
		return WeixinHttpClient.request(policy);
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#addNews(java.util.List)
	 */
	@Override
	public GraphicsTextMaterials addNews(List<GraphicsTextMaterial> materials) throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		RequestPolicy<GraphicsTextMaterials> policy = new JsonRequestPolicy<GraphicsTextMaterials>(
				URLConstants.Material.URL_MATERIAL_ADDNEWS,
				WeixinConfig.ENCODING,
				params, new GraphicsTextMaterials(materials), GraphicsTextMaterials.class);
		GraphicsTextMaterials result = WeixinHttpClient.request(policy);
		result.setArticles(materials);
		result.setNews_item(materials);
		return result;
	}
	
	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#updateNews(com.dev.weixin.tools.models.material.GraphicsTextMaterials)
	 */
	@Override
	public boolean updateNews(GraphicsTextMaterials materials)
			throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		RequestPolicy<ErrorMsg> policy = new JsonRequestPolicy<ErrorMsg>(
				URLConstants.Material.URL_MATERIAL_UPDATENEWS,
				WeixinConfig.ENCODING,
				params, materials, ErrorMsg.class);
		ErrorMsg error = WeixinHttpClient.request(policy);
		boolean isOk = error != null && StringUtils.equals("0", error.getErrcode());
		if(!isOk) {
			throw new ErrorMsgException(error);
		}
		return isOk;
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#addMaterial(java.lang.String, java.io.File)
	 */
	@Override
	public Material addMaterial(String type, File file)
			throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		params.put("type", type);
		Map<String, Object> body = new LinkedHashMap<String, Object>();
		body.put("media", file);
		RequestPolicy<Material> policy = new UploadRequestPolicy<Material>(
				URLConstants.Material.URL_MATERIAL_ADDMATERIAL,
				WeixinConfig.ENCODING,
				params, body, Material.class);
		Material material = WeixinHttpClient.request(policy);
		material.setType(type);
		return material;
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#addVideoMaterial(java.io.File)
	 */
	@Override
	public VideoMaterial addVideoMaterial(String title, String introduction, File file) throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		params.put("type", "video");
		VideoMaterial m = new VideoMaterial();
		m.setTitle(title);
		m.setIntroduction(introduction);
		Map<String, Object> body = new LinkedHashMap<String, Object>();
		body.put("media", file);
		body.put("description", m);
		RequestPolicy<VideoMaterial> policy = new UploadRequestPolicy<VideoMaterial>(
				URLConstants.Material.URL_MATERIAL_ADDMATERIAL,
				WeixinConfig.ENCODING,
				params, body, VideoMaterial.class);
		VideoMaterial material = WeixinHttpClient.request(policy);
		m.setType("video");
		m.setMedia_id(material.getMedia_id());
		return m;
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#getGraphicsTextMaterials(java.lang.String)
	 */
	@Override
	public GraphicsTextMaterials getGraphicsTextMaterials(String media_id) throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		Map<String, String> body = new HashMap<String, String>();
		body.put("media_id", media_id);
		RequestPolicy<GraphicsTextMaterials> policy = new JsonRequestPolicy<GraphicsTextMaterials>(
				URLConstants.Material.URL_MATERIAL_GETMATERIAL, 
				WeixinConfig.ENCODING,
				params, body, GraphicsTextMaterials.class);
		GraphicsTextMaterials materials = WeixinHttpClient.request(policy);
		materials.setArticles(materials.getNews_item());
		materials.setMedia_id(media_id);
		return materials;
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#getVideoMaterial(java.lang.String)
	 */
	@Override
	public VideoMaterialGet getVideoMaterial(String media_id)
			throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		Map<String, String> body = new HashMap<String, String>();
		body.put("media_id", media_id);
		RequestPolicy<VideoMaterialGet> policy = new JsonRequestPolicy<VideoMaterialGet>(
				URLConstants.Material.URL_MATERIAL_GETMATERIAL, 
				WeixinConfig.ENCODING,
				params, body, VideoMaterialGet.class);
		VideoMaterialGet video = WeixinHttpClient.request(policy);
		video.setMedia_id(media_id);
		return video;
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#getMaterial(java.lang.String, java.lang.String)
	 */
	@Override
	public File getMaterial(String media_id, String filepath)
			throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		Map<String, String> body = new HashMap<String, String>();
		body.put("media_id", media_id);
		RequestPolicy<File> policy = new ForceDownloadRequestPolicy(
				URLConstants.Material.URL_MATERIAL_GETMATERIAL,
				WeixinConfig.ENCODING,
				params, body, filepath);
		return WeixinHttpClient.request(policy);
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#removeMaterial(java.lang.String)
	 */
	@Override
	public boolean removeMaterial(String media_id) throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		Map<String, String> body = new HashMap<String, String>();
		body.put("media_id", media_id);
		RequestPolicy<ErrorMsg> policy = new JsonRequestPolicy<ErrorMsg>(
				URLConstants.Material.URL_MATERIAL_DELMATERIAL,
				WeixinConfig.ENCODING,
				params, body, ErrorMsg.class);
		ErrorMsg error = WeixinHttpClient.request(policy);
		boolean isOk = error != null && StringUtils.equals("0", error.getErrcode());
		if(!isOk) {
			throw new ErrorMsgException(error);
		}
		return isOk;
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#getMaterialCount()
	 */
	@Override
	public MaterialCount getMaterialCount() throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		RequestPolicy<MaterialCount> policy = new GetRequestPolicy<MaterialCount>(
				URLConstants.Material.URL_MATERIAL_GETMATERIALCOUNT,
				WeixinConfig.ENCODING,
				params, MaterialCount.class);
		return WeixinHttpClient.request(policy);
	}

	/* (non-Javadoc)
	 * @see com.dev.weixin.tools.service.MaterialService#getMaterialList(java.lang.String, int, int)
	 */
	@Override
	public MaterialList getMaterialList(String type, int offset, int count)
			throws ErrorMsgException {
		Map<String, String> params = new HashMap<String, String>();
		params.put("access_token", this.baseService.getAccessToken());
		Map<String, Object> body = new HashMap<String, Object>();
		body.put("type", type);
		body.put("offset", offset);
		body.put("count", count);
		RequestPolicy<MaterialList> policy = new JsonRequestPolicy<MaterialList>(
				URLConstants.Material.URL_MATERIAL_GETMATERIALCOUNT,
				WeixinConfig.ENCODING,
				params, body, MaterialList.class);
		return WeixinHttpClient.request(policy);
	}

}
